package cn.stylefeng.guns.modular.app.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.stylefeng.guns.modular.app.controller.market.Kline;
import cn.stylefeng.guns.modular.app.dto.ApiWalletDto;
import cn.stylefeng.guns.modular.app.entity.Member;
import cn.stylefeng.guns.modular.app.vo.e.ApiWalletVo;
import cn.stylefeng.guns.modular.base.state.Constant;
import cn.stylefeng.guns.modular.base.state.F;
import cn.stylefeng.guns.modular.base.state.ProConst;
import cn.stylefeng.guns.modular.base.util.RedisUtil;
import cn.stylefeng.guns.modular.base.util.Result;
import cn.stylefeng.guns.modular.coin.entity.Futures;
import cn.stylefeng.guns.modular.coin.entity.Spot;
import cn.stylefeng.guns.modular.coin.entity.Swap;
import cn.stylefeng.guns.modular.e.entity.Match;
import cn.stylefeng.guns.modular.e.service.MatchService;
import cn.stylefeng.guns.modular.fin.entity.Currency;
import cn.stylefeng.guns.modular.fin.entity.*;
import cn.stylefeng.guns.modular.fin.service.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class HomeWalletService extends Constant {
    @Autowired
    private LegalService legalService;
    @Autowired
    private FinFuturesService finFuturesService;
    @Autowired
    private WalletService walletService;
    @Autowired
    private FinMiningService finMiningService;
    @Autowired
    private ProfitService profitService;

    @Autowired
    private CurrencyService currencyService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private FinOptionService finOptionService;

    @Autowired
    private CashflowService cashflowService;

    @Autowired
    private ContractService contractService;
    @Autowired
    private MatchService matchService;


    public Result wallet(String token, ApiWalletVo vo) {
        //region 初始化赋值
        //估值总额
        BigDecimal valuationTotalPrice = BigDecimal.ZERO;
        //账户总额
        BigDecimal accountTotalPrice = BigDecimal.ZERO;
        //钱包折合
     //   BigDecimal walletConvert = BigDecimal.ZERO;
        //币币折合
//        BigDecimal currencyConvert = BigDecimal.ZERO;
        //期权折合
      //  BigDecimal optionConvert = BigDecimal.ZERO;
        //合约折合
      //  BigDecimal contractConvert = BigDecimal.ZERO;
        //黄金折合
     //   BigDecimal futuresConvert = BigDecimal.ZERO;
        //法币折合
  //      BigDecimal legalConvert = BigDecimal.ZERO;
        //矿机折合
      //  BigDecimal miningConvert = BigDecimal.ZERO;
        // 今日总收益
        BigDecimal incomeTotal = BigDecimal.ZERO;
        // 累计总收益
        BigDecimal incomeTotals = BigDecimal.ZERO;
        //endregion

        List<ApiWalletDto> list = new ArrayList<>();
        List<Spot> spots = F.me().getSpots(null);

        //region 钱包账户
        Member member = (Member) redisUtil.get(token);


        //region 币币账户
        Currency currencyQ = new Currency();
        currencyQ.setDel("N");
        currencyQ.setMemberId(member.getMemberId());
        List<Currency> currencyList = currencyService.list(new QueryWrapper<>(currencyQ));
        currencyList.sort(Comparator.comparing(Currency::getSort));
        for (Currency entity : currencyList) {
            Kline map = (Kline) redisUtil.get(KINE + entity.getType() + "/USDT" + _NEW);
            if (map == null) {
                map = new Kline();
                map.setClose(0);
            }
            BigDecimal close = new BigDecimal(map.getClose());
            BigDecimal total = entity.getUsedPrice().add(entity.getReleasePledgeNum()).add(entity.getLockedPrice());
            if (vo.getType().equals("CURRENCY") ) {
                ApiWalletDto dto = new ApiWalletDto();
                for (Spot spot : spots) {
                    if (spot.getSymbol().equals(entity.getType() + "/USDT")) {
                        dto.setImg(spot.getImg());
                    }
                }
                dto.setType(entity.getType());
                dto.setReleasePledgeNum(entity.getReleasePledgeNum());
                dto.setUsedPrice((entity.getUsedPrice() == null ? BigDecimal.ZERO : entity.getUsedPrice()).toPlainString());
                dto.setLockedPrice(entity.getLockedPrice().toPlainString());

                dto.setId(entity.getCurrencyId());
                dto.setTotalPrice(total.toPlainString());

                dto.setClose(close.toPlainString());
                valuationTotalPrice = valuationTotalPrice.add(close.multiply(total));


                if (StrUtil.equals(vo.getHide(), "Y") && new BigDecimal(dto.getTotalPrice()).compareTo(BigDecimal.ZERO) == 0)
                    continue;


                // String debugStr = "币币账户---币种:{}, 当前币数:{}, 0点币数:{}, 当前价格:{}, 0点价格:{}, 每日收益:{}, 收益率:{}";
                // System.err.println(StrUtil.format(debugStr, entity.getType(), total, zeroTimeCoin, close, zeroPrice, dailyIncome, rate));

                if (vo.getType().equals("CURRENCY")) {
                    list.add(dto);
                }
            }

        }

        if (vo.getType().equals("CURRENCY") ) {
            // 获取累计收益
            List<Profit> currencyProfitList = profitService.list(new LambdaUpdateWrapper<Profit>()
                    .eq(Profit::getMemberId, member.getMemberId())
                    .eq(Profit::getWalletType, WalletBigType.CURRENCY.code)
            );
            if (CollUtil.isNotEmpty(currencyProfitList)) {
                for (Profit item : currencyProfitList) {
                    incomeTotals = incomeTotals.add(new BigDecimal(item.getProfitPrice()));
                }
            }
        }
        //endregion

        //region 返回数据
        Map<String, Object> map = new HashMap<>();
        map.put("valuationTotalPrice", valuationTotalPrice.toPlainString());
        map.put("accountTotalPrice", accountTotalPrice.toPlainString());
        map.put("list", list);
        map.put("incomeTotal", incomeTotal); // 今日总收益
        map.put("incomeTotals", incomeTotals); // 累计总收益
        return success("资产信息", map);
        //endregion
    }

    private void genFinFutures(Member m) {
        List<Futures> swapList = F.me().getFuturess(null);
        for (Futures swap : swapList) {
            //String coin = swap.getSymbol().split("/")[0];
            String coin = swap.getSymbol().split("/")[1];
            if ("USDT-TRC20".equals(coin) || "USDT-ERC20".equals(coin) || "USDT-OMNI".equals(coin)) {
                coin = "USDT";
            }
            FinFutures query = F.me().getFinFutures(m.getMemberId(), coin);
            if (query != null)
                continue;
            FinFutures contract = new FinFutures();
            contract.setMemberId(m.getMemberId());
            contract.setType(coin);
            contract.setUsedPrice(BigDecimal.ZERO);
            contract.setEntrustPrice(BigDecimal.ZERO);
            contract.setPositionPrice(BigDecimal.ZERO);
            contract.setCreateUser(m.getMemberId());
            contract.setUpdateUser(m.getMemberId());
            finFuturesService.save(contract);
        }
    }

    private BigDecimal getTransfersAsset(Date beginTime, Date endTime, Long memberId, String coinType, String walletType) {
        BigDecimal transfersAsset = BigDecimal.ZERO;
        LambdaQueryWrapper<Cashflow> qw = new LambdaQueryWrapper<Cashflow>()
                .eq(Cashflow::getMemberId, memberId)
                .eq(Cashflow::getWalletType, walletType)
                .eq(Cashflow::getFlowCoin, coinType)
                .in(Cashflow::getFlowType, ProConst.CashFlowTypeEnum.PLATFORM_ADD.getCode(), ProConst.CashFlowTypeEnum.CONVERT_IN.getCode())
                .between(Cashflow::getCreateTime, beginTime, endTime)
                .orderByDesc(Cashflow::getCreateTime);
        List<Cashflow> cashflowList = cashflowService.list(qw);

        if (CollUtil.isNotEmpty(cashflowList)) {
            transfersAsset = cashflowList.stream()
                    .map(Cashflow::getFlowPrice)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        }

        return transfersAsset;
    }

}
